/*
 * Copyright 2018 Vivliostyle Foundation
 *
 * This file is part of Vivliostyle UI.
 *
 * Vivliostyle UI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Vivliostyle UI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Vivliostyle UI.  If not, see <http://www.gnu.org/licenses/>.
 */

import ko from "knockout";

const supportTouchEvents = "ontouchstart" in window;

let xStart = null;
let yStart = null;
let arrowButton = null;

declare global {
  interface Window {
    visualViewport?: {
      offsetLeft: Readonly<number>;
      offsetTop: Readonly<number>;
      pageLeft: Readonly<number>;
      pageTop: Readonly<number>;
      width: Readonly<number>;
      height: Readonly<number>;
      scale: Readonly<number>;
    };
  }
}

ko.bindingHandlers.swipePages = {
  init(element, valueAccessor) {
    if (supportTouchEvents && ko.unwrap(valueAccessor())) {
      element.addEventListener("touchstart", event => {
        if (event.touches.length > 1) {
          return; // multi-touch is not for page swipe
        }
        if (window.visualViewport && window.visualViewport.scale > 1) {
          return; // disable page swipe when pinch-zoomed
        }
        const viewportElement = document.getElementById(
          "vivliostyle-viewer-viewport"
        );
        if (
          viewportElement &&
          viewportElement.scrollWidth > viewportElement.clientWidth
        ) {
          return; // disable page swipe when horizontal scrollable
        }
        xStart = event.touches[0].clientX;
        yStart = event.touches[0].clientY;
      });
      element.addEventListener("touchmove", event => {
        if (event.touches.length > 1) {
          return;
        }
        if (xStart !== null && yStart !== null) {
          const xDiff = event.touches[0].clientX - xStart;
          const yDiff = event.touches[0].clientY - yStart;
          if (Math.abs(xDiff) > Math.abs(yDiff)) {
            if (xDiff < 0) {
              // swipe to left = go to right
              arrowButton = document.getElementById(
                "vivliostyle-page-navigation-right"
              );
            } else {
              // swipe to right = go to left
              arrowButton = document.getElementById(
                "vivliostyle-page-navigation-left"
              );
            }
          }
          if (Math.abs(xDiff) + Math.abs(yDiff) >= 16) {
            if (arrowButton) {
              arrowButton.click();
              ko.utils.toggleDomNodeCssClass(arrowButton, "active", true);
            }
            xStart = null;
            yStart = null;
          }
        }
      });
      element.addEventListener("touchend", () => {
        if (arrowButton) {
          ko.utils.toggleDomNodeCssClass(arrowButton, "active", false);
        }
        arrowButton = null;
        xStart = null;
        yStart = null;
      });
    }
  }
};
